// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// r [author] rhyme_lph
// K [email]  rhymelph@gmail.com
// p [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/business_contact_entity.dart';
import 'package:finance_app/src/entities/common_currency_rate_entity.dart';
import 'package:finance_app/src/entities/ocr_attachment_entity.dart';
import 'package:finance_app/src/entities/quotation_detail_entity.dart';
import 'package:finance_app/src/entities/quotation_entity.dart';
import 'package:finance_app/src/entities/setting_data_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/http_service/http_quotation_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/discount_mixin.dart';
import 'package:finance_app/src/mixin/form_products_or_services_mixin.dart';
import 'package:finance_app/src/mixin/from_attach_mixin.dart';
import 'package:finance_app/src/mixin/init_edit_data_mixin.dart';
import 'package:finance_app/src/provider/dashboard/sales/sales_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/views/sales_quotation_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/views/sales_summary_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/cash_utils.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/calendar_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/currency_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/judge_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:quiver/strings.dart';

class NewQuotationProvider extends BaseProvider<QuotationDetailEntity>
    with FormAttachMixin, FormProductsOrServicesMixin, DiscountMixin, InitEditDataMixin<QuotationDetailEntity>, CheckPlanMixin {
  TextEditingController quotationNumberController = TextEditingController();
  FocusNode quotationNumberFocusNode = FocusNode();
  TextEditingController notesController = TextEditingController();
  FocusNode notesFocusNode = FocusNode();

  DateTime validUntil;

  SettingDataCurrency currency;
  SettingDataCurrency normalCurrency;
  String changeAmount = '0.00';

  BusinessContactEntity client;

  List<String> menuList = [
    'Edit',
    'Delete',
  ];

  bool isSelectMode = false;

  bool isDelivered = false;

  NewQuotationProvider() {}

  @override
  void dispose() {
    super.dispose();
    quotationNumberController.dispose();
    notesController.dispose();
    notesFocusNode.dispose();
    quotationNumberFocusNode.dispose();
  }

  @override
  void initState() {
    super.initState();
  }

  void unFocus() {
    notesFocusNode.unfocus();
    quotationNumberFocusNode.unfocus();
  }

  void onSave() async {
    unFocus();
    if (client == null) {
      showToast(S.current.please_select_client_name);
      return;
    }

    if (quotationNumberController.text.length == 0) {
      showToast(S.current.please_enter_the_quotation_number);
      return;
    }

    if (date == null) {
      showToast(S.current.please_select_issue_date);
      return;
    }

    if (validUntil == null) {
      showToast(S.current.please_select_valid_until);
      return;
    }

    if (currency == null) {
      showToast(S.current.please_select_currency);
      return;
    }

    if (serviceAndProductList.length == 0) {
      showToast(S.current.please_add_item);
      return;
    }

    List item = serviceAndProductList
        .map((e) => {
              'type': e.product != null && e.product.id != null ? 'product' : 'service',
              'type_id': e.id,
              'name': e.name,
              'quantity': e.number,
              'price': e.price,
              'is_tax_inclusive': e.isInclusive ? 1 : 0,
              'tax_id': e.tax.id,
              'tax_amount': e.taxAmount,
              'discount_type': e.discountType,
              'discount_value': e.discountValue,
            })
        .toList();
    List<int> attachmentIds = await uploadFiles();
    if (attachmentIds == null) return;

    QuotationEntity orderEntity;
    if (isEdit == true) {
      await post(
          HttpQuotationService.updateQuotations(
            data.id,
            item: item,
            contactId: client.id,
            total: totalDiscount,
            number: quotationNumberController.text,
            subtotal: subTotal,
            currency_code: currency.key,
            issued_at: DateTimeUtils.formatDateTime(date, 'yyyy-MM-dd'),
            due_at: DateTimeUtils.formatDateTime(validUntil, 'yyyy-MM-dd'),
            inclusive_tax_amount: includesGST,
            exclusive_tax_amount: gst,
            notes: notesController.text,
            discount_type: discountType,
            discount_amount: discountAmount,
            attachment_ids: attachmentIds,
          ),
          autoHandler: AutoHandler.Toast, onSuccess: (result) {
        orderEntity = getEntityFromResult<QuotationEntity>(result);
      });
    } else {
      await post(
          HttpQuotationService.createQuotations(
            item: item,
            contactId: client.id,
            total: totalDiscount,
            number: quotationNumberController.text,
            subtotal: subTotal,
            currency_code: currency.key,
            issued_at: DateTimeUtils.formatDateTime(date, 'yyyy-MM-dd'),
            due_at: DateTimeUtils.formatDateTime(validUntil, 'yyyy-MM-dd'),
            inclusive_tax_amount: includesGST,
            exclusive_tax_amount: gst,
            notes: notesController.text,
            discount_type: discountType,
            discount_amount: discountAmount,
            attachment_ids: attachmentIds,
          ),
          autoHandler: AutoHandler.Toast, onSuccess: (result) {
        orderEntity = getEntityFromResult<QuotationEntity>(result);
      });
    }

    if (orderEntity != null) {
      updateDashboard();

      if (isSelectMode == true) {
        obtainContext?.call((context) {
          Navigator.of(context).pop(orderEntity);
        });
      } else {
        id = orderEntity.id;
        await post(editDataFuture, loadingTip: S.current.loading, autoHandler: AutoHandler.Toast, onSuccess: (result) {
          isEdit = false;
          data = transformData(getEntityFromResult<QuotationDetailEntity>(result), false);
          update();
        });
      }
    }
  }

  void onChangeClientName() async {
    unFocus();
    final result = await Routes.navigateTo(RouterGenProviders.businessContactsPage, params: {
      'select': client,
    });
    if (result != null) {
      client = result;
      update();
    }
  }

  void onChangeIssueDate() {
    unFocus();
    obtainContext?.call((context) async {
      date = await showCalendarBottomSheet(context, date);
      update();
    });
  }

  void onChangeValidUntil() {
    unFocus();
    obtainContext?.call((context) async {
      validUntil = await showCalendarBottomSheet(context, validUntil, startDate: date, withinFinancialYear: false);
      update();
    });
  }

  void onChangeCurrency() {
    unFocus();
    obtainContext?.call((context) async {
      currency = await showCurrencyBottomSheet(context, currency);
      update();
      _getCurrencyChange();
    });
  }

  _getCurrencyChange() async {
    await post(
        HttpQuotationService.currencyRate(
            '${date.year}-${date.month >= 10 ? date.month : '0${date.month}'}-${date.day >= 10 ? date.day : '0${date.day}'}', currency.key),
        loadingTip: S.current.loading,
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      var datas = result.data['data'];
      if (datas != null) {
        CommonCurrencyRateEntity entity = CommonCurrencyRateEntity.fromJson(datas);
        var amount = '0.00';
        if (entity != null || isNotEmpty(entity.rate)) {
          amount = double.parse('${entity.rate}').toStringAsFixed(2);
        }
        changeAmount = amount;
        update();
        logger.d("--> $changeAmount");
      }
    });
  }

  amountChange(String value){

  }

  @override
  Future get editDataFuture => HttpQuotationService.showQuotations(id);

  @override
  FutureOr<QuotationDetailEntity> transformData(QuotationDetailEntity d, bool isCache) {
    client = d.contact;
    quotationNumberController.text = d.number;
    date = DateTimeUtils.toDateTime(d.issuedAt);
    validUntil = DateTimeUtils.toDateTime(d.dueAt);
    isDelivered = d.deliveredAt != null;
    currency = Config.settingData.currency.firstWhere((element) => element.key == d.currencyCode, orElse: () => null);
    serviceAndProductList = d.items.map((e) => e.toServiceAndProduct()).toList();
    notesController.text = d.notes;
    if (d.discountType != null) {
      if (d.discountType == 'value') {
        discountValue = CashUtils.formatCashAmount2(d.discountAmount);
      } else {
        discountValue = '${d.discountAmount}%';
      }
    }
    if (d.status == 'rejected') {
      menuList = ['Delete'];
    } else if (d.status == 'accepted') {
      menuList = ['Delete', 'See Invoice', S.current.share_in_pdf];
    } else if (d.status == 'closed') {
      menuList = ['Delete', 'See Invoice', S.current.share_in_pdf];
    } else {
      menuList = ['Edit', 'Delete', 'Generate Invoice', 'Generate DO', S.current.share_in_pdf];
      // if (d.deliveredAt == null) {
      //   menuList.add('Mark As Delivered');
      // }
    }
    if (isDelivered) {
      menuList.remove('Edit');
    }
    handleDataUpdate(d);
    return super.transformData(d, isCache);
  }

  void onSelectMenu(String value) {
    switch (value) {
      case 'Edit':
        onChangeEditMode();
        break;
      case 'Delete':
        onDelete();
        break;
      case 'Share in PDF':
      case '分享PDF':
        onShare();
        break;
      case 'Generate Invoice':
        onGenerateInvoice();
        break;
      case 'Generate DO':
        onGenerateDelivery();
        break;
      case 'Mark As Delivered':
        onMarkAsDelivered();
        break;
      case 'See Invoice':
        onSeeInvoice();
        break;
    }
  }

  void onSeeInvoice() async {
    await Routes.navigateTo(RouterGenProviders.newInvoicePage, params: {'data': TransactionEntity()..transactionableId = data.invoiceId});
    onTry();
    updateDashboard();
  }

  //
  // void onGeneratePO() async {
  //   final result =
  //       Routes.navigateTo(RouterGenProviders.newPurchaseOrderPage, params: {
  //     'generate': data,
  //   });
  //   if (result != null) {
  //     onTry();
  //   }
  // }

  void onGenerateInvoice() async {
    if (isPlanExpired()) return;
    final result = await Routes.navigateTo(RouterGenProviders.newInvoicePage, params: {
      'generate': data,
      'isSelectMode': true,
    });
    if (result != null) {
      onTry();
      updateDashboard();
    }
  }

  void onGenerateDelivery() async {
    if (isPlanExpired()) return;
    final result = await Routes.navigateTo(RouterGenProviders.deliveryOrderPage, params: {
      'id': data.id,
    });
    if (result != null) {
      onTry();
    }
  }

  void onReject() async {
    obtainContext?.call((context) async {
      bool isSuccess = await showMarkAsRejectedInfoBottomSheet(context);
      if (isSuccess == true) {
        isSuccess = false;
        QuotationDetailEntity detailEntity;
        await post(HttpQuotationService.rejectedQuotation(id), loadingTip: S.current.loading, autoHandler: AutoHandler.Toast, onSuccess: (result) {
          isSuccess = true;
          detailEntity = getEntityFromResult<QuotationDetailEntity>(result);
        });
        if (detailEntity != null) {
          await showQuotationMarkedAsRejectedSuccessTipBottomSheet(context);
          data = transformData(detailEntity, false);
          update();
          updateDashboard();
        }
      }
    });
  }

  void onDelete() {
    if (isPlanExpired()) return;
    obtainContext?.call((context) async {
      bool isSuccess = await showDeleteTransactionInfoBottomSheet(context);
      if (isSuccess == true) {
        isSuccess = false;
        await post(HttpQuotationService.deleteQuotation(data.id), loadingTip: S.current.loading, autoHandler: AutoHandler.Toast, onSuccess: (result) {
          isSuccess = true;
        });
        if (isSuccess == true) {
          await showDeleteSuccessTipBottomSheet(context);
          Navigator.of(context).pop({
            'delete': true,
          });
          updateDashboard();
        }
      }
    });
  }

  void onMarkAsDelivered() {
    if (isPlanExpired()) return;
    obtainContext?.call((context) async {
      bool isSuccess = await showMarkTheItemsAsDeliveredAsJudgeBottomSheet(context);
      if (isSuccess == true) {
        isSuccess = false;
        await post(HttpQuotationService.deliver(id), loadingTip: S.current.loading, autoHandler: AutoHandler.Toast, onSuccess: (result) {
          isSuccess = true;
        });
        if (isSuccess == true) {
          await showMarkedAsDeliveredSuccessTipBottomSheet(context);
          onTry();
        }
      }
    });
  }

  void updateDashboard() {
    Providers.get<SalesProvider>(RouterGenProviders.salesPage, null)?.getChildProvider<SalesQuotationProvider>()?.onRefresh();
    Providers.get<SalesProvider>(RouterGenProviders.salesPage, null)?.getChildProvider<SalesSummaryProvider>()?.onRefresh();
  }

  @override
  List<OcrAttachmentEntity> get attachments => data?.attachments;

  @override
  String get type => 'quotation';

  @override
  TextEditingController get numberCtl => quotationNumberController;
}
